package cl.minvu.catastro.util;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;

import cl.minvu.catastro.model.AccesoVivienda;
import cl.minvu.catastro.model.Comuna;
import cl.minvu.catastro.model.CondicionOcupacion;
import cl.minvu.catastro.model.DanoVivienda;
import cl.minvu.catastro.model.Detalleinstalaciondomiciliaria;
import cl.minvu.catastro.model.Direccion;
import cl.minvu.catastro.model.Encuestado;
import cl.minvu.catastro.model.Encuestador;
import cl.minvu.catastro.model.Ficha;
import cl.minvu.catastro.model.Genero;
import cl.minvu.catastro.model.GrupoPrincipal;
import cl.minvu.catastro.model.GrupoSecundario;
import cl.minvu.catastro.model.HabitacionTransitoria;
import cl.minvu.catastro.model.InstalacionDomiciliaria;
import cl.minvu.catastro.model.Intervencion;
import cl.minvu.catastro.model.ItemDano;
import cl.minvu.catastro.model.MaterialPredominante;
import cl.minvu.catastro.model.ModalidadConstructiva;
import cl.minvu.catastro.model.Moradore;
import cl.minvu.catastro.model.OcupacionVivienda;
import cl.minvu.catastro.model.Persona;
import cl.minvu.catastro.model.Region;
import cl.minvu.catastro.model.SistemaAgrupamiento;
import cl.minvu.catastro.model.SituacionVivienda;
import cl.minvu.catastro.model.TipoCatastrofe;
import cl.minvu.catastro.model.TipoDanoVivienda;
import cl.minvu.catastro.model.TipoInstalacion;
import cl.minvu.catastro.model.TipologiaVivienda;
import cl.minvu.catastro.model.VisitaEstructural;
import cl.minvu.catastro.model.Zona;

/**
 * @author psep
 * 
 */
public final class CastUtil {

	private static final Logger logger = Logger.getLogger(CastUtil.class);

	/**
	 * @param json
	 * @param foto
	 * @return
	 */
	public static final Ficha getFicha(String json, String foto) {
		Ficha ficha = null;

		try {
			JSONObject fichaJson = new JSONObject(json);
			Ficha f = new Ficha();

			// Process direccion
			JSONObject direccionJson = fichaJson.getJSONObject("direccion");
			JSONObject comunaJson = direccionJson.getJSONObject("comuna");
			Direccion direccion = new Direccion();
			Comuna comuna = new Comuna();
			comuna.setIdcomuna((Integer) jsonGetById(comunaJson, "id"));
			direccion.setComuna(comuna);
			direccion.setVillaconjuntopoblacion((String) jsonGetById(
					direccionJson, "villa"));
			direccion.setManzanasitio((String) jsonGetById(direccionJson,
					"otros"));
			direccion.setCasa((String) jsonGetById(direccionJson, "casa"));
			direccion.setDepartamento((String) jsonGetById(direccionJson,
					"depto"));
			direccion.setPiso((String) jsonGetById(direccionJson, "piso"));
			direccion.setBlock((String) jsonGetById(direccionJson, "block"));
			
			// Zona
			Integer idZona = getIntFromCombobox(direccionJson, "zona");
			
			if (idZona != null) {
				Zona zona = new Zona();
				zona.setIdzona(idZona);
				direccion.setZona(zona);
			}
			
			direccion.setNumero(Integer.toString((Integer) jsonGetById(
					direccionJson, "numeracion")));
			direccion.setCalle((String) jsonGetById(direccionJson, "calle"));
			f.setDireccion(direccion);

			TipoCatastrofe tipoCatastrofe = new TipoCatastrofe();
			tipoCatastrofe.setIdtipocatastrofe((Integer) jsonGetById(fichaJson,
					"tipoCatastro"));
			f.setTipoCatastrofe(tipoCatastrofe);

			Integer idMoradores = getIntFromCombobox(fichaJson, "moradores");
			
			if (idMoradores != null) {
				Moradore tipoMoradores = new Moradore();
				tipoMoradores.setIdmorador(idMoradores);
				f.setMoradore(tipoMoradores);
			}

			f.setEncuestado(getEncuestado(fichaJson, direccionJson));

			JSONObject diagnosticoJson = fichaJson.getJSONObject("diagnostico");
			
			Integer idTipologia = getIntFromCombobox(diagnosticoJson, "tipologia");
			
			if (idTipologia != null) {
				TipologiaVivienda tipologiaVivienda = new TipologiaVivienda();
				tipologiaVivienda.setIdtipologiavivienda(idTipologia);
				f.setTipologiaVivienda(tipologiaVivienda);
			}
			
			Integer idModalidad = getIntFromCombobox(diagnosticoJson, "modalidad");
			
			if (idModalidad != null) {
				ModalidadConstructiva constructiva = new ModalidadConstructiva();
				constructiva.setIdmodalidadconstruccion(idModalidad);
				f.setModalidadConstructiva(constructiva);
			}
			
			Integer idAgrupamiento = getIntFromCombobox(diagnosticoJson, "agrupamiento");
			
			if (idAgrupamiento != null) {
				SistemaAgrupamiento agrupamiento = new SistemaAgrupamiento();
				agrupamiento.setIdsistemaagrupamiento(idAgrupamiento);
				f.setSistemaAgrupamiento(agrupamiento);
			}
			
			Integer idMaterialPred = getIntFromCombobox(diagnosticoJson, "material");
			
			if (idMaterialPred != null) {
				MaterialPredominante predominante = new MaterialPredominante();
				predominante.setIdmaterialpredominante(idMaterialPred);
				f.setMaterialPredominante(predominante);
			}	
			
			f.setNumeropisos((Integer) jsonGetById(diagnosticoJson, "pisos"));

			JSONObject situacionJson = fichaJson
					.getJSONObject("situacionVivienda");
			
			Integer idIntervencion = getIntFromCombobox(situacionJson, "intervencion");
			
			if (idIntervencion != null) {
				Intervencion intervencion = new Intervencion();
				intervencion.setIdintervencion(idIntervencion);
				f.setIntervencion(intervencion);
			}
			
			Integer idSituacion = getIntFromCombobox(situacionJson, "tipoDanio");
			
			if (idSituacion != null) {
				SituacionVivienda situacionVivienda = new SituacionVivienda();
				situacionVivienda.setIdsituacionvivienda(idSituacion);
				f.setSituacionVivienda(situacionVivienda);
			}
			
			Integer idEstructural = getIntFromCombobox(situacionJson, "visitaIngEstructural");
			
			if (idEstructural != null) {
				VisitaEstructural estructural = new VisitaEstructural();
				estructural.setIdvisitaestructural(idEstructural);
				f.setVisitaEstructural(estructural);
			}

			f.setFoto(stringToBytes(foto));
			f.setObservacion((String) jsonGetById(fichaJson, "observaciones"));
			f.setFechaingreso(DateUtil.strToDate((String) jsonGetById(
					fichaJson, "fechaVisita")));

			// Encuestador
			JSONObject userJson = fichaJson.getJSONObject("user");
			Encuestador encuestador = new Encuestador();
			Persona persona2 = new Persona();
			persona2.setRut(new BigInteger(Integer
					.toString((Integer) jsonGetById(userJson, "run"))));
			encuestador.setPassword((String) jsonGetById(userJson, "passwd"));
			encuestador.setToken((String) jsonGetById(userJson, "token"));
			encuestador.setPersona(persona2);
			f.setEncuestador(encuestador);

			ficha = f;

		} catch (Exception e) {
			logger.error("Error al castear Ficha");
		}

		return ficha;
	}
	
	/**
	 * @param json
	 * @param key
	 * @return
	 */
	public static final Integer getIntFromCombobox(JSONObject json, String key) {
		Integer id = (Integer) jsonGetById(json, key);
		
		if (id != null && id == 0) {
			return null;
		} else {
			return id;
		}
	}

	/**
	 * @param fichaJson
	 * @param direccionJson
	 * @return
	 */
	public static final Encuestado getEncuestado(JSONObject fichaJson,
			JSONObject direccionJson) {

		try {
			JSONObject encuestadoJson = fichaJson.getJSONObject("encuestado");
			
			Encuestado encuestado = new Encuestado();
			Persona persona = new Persona();
			persona.setDigitoverificador((String) jsonGetById(encuestadoJson,
					"dv"));
			Genero genero = new Genero();
			genero.setIdgenero((Integer) jsonGetById(encuestadoJson, "genero"));
			persona.setGenero(genero);
			persona.setNombres((String) jsonGetById(encuestadoJson, "nombres"));
			persona.setApellidopaterno((String) jsonGetById(encuestadoJson,
					"apellidoPaterno"));
			persona.setApellidomaterno((String) jsonGetById(encuestadoJson,
					"apellidoMaterno"));
			persona.setRut(new BigInteger(Integer
					.toString((Integer) jsonGetById(encuestadoJson, "run"))));

			if (persona.getRut() == null) {
				return null;
			}

			persona.setNacionalidad((String) jsonGetById(encuestadoJson,
					"nacionalidad"));
			persona.setTelefono((Integer) jsonGetById(direccionJson, "telefono"));
			encuestado.setPersona(persona);
			JSONObject prinJson = fichaJson.getJSONObject("mainGroup");
			GrupoPrincipal principal = new GrupoPrincipal();
			principal.setNumeromenores((Integer) jsonGetById(prinJson,
					"menores"));
			principal.setNumeroadultosmayores((Integer) jsonGetById(prinJson,
					"mayores"));
			principal.setNumeroadultos((Integer) jsonGetById(prinJson,
					"adultos"));
			principal.setRequerimientosespeciales((Integer) jsonGetById(
					prinJson, "discapacitados"));
			encuestado.setGrupoPrincipal(principal);
			
			Integer idHabitacion = getIntFromCombobox(prinJson, "lugarTemporal");
			
			if (idHabitacion != null) {
				HabitacionTransitoria habitacionTransitoria = new HabitacionTransitoria();
				habitacionTransitoria.setIdhabitaciontransitoria(idHabitacion);
				encuestado.setHabitacionTransitoria(habitacionTransitoria);
			}
			
			Integer idAcceso = getIntFromCombobox(prinJson,"subsidio");
			
			if (idAcceso != null) {
				AccesoVivienda accesoVivienda = new AccesoVivienda();
				accesoVivienda.setIdaccesovivienda(idAcceso);
				encuestado.setAccesoVivienda(accesoVivienda);
			}
			
			Integer idCondicion = getIntFromCombobox(prinJson, "condicionOcupacion");
			
			if (idCondicion != null) {
				CondicionOcupacion condicionOcupacion = new CondicionOcupacion();
				condicionOcupacion.setIdcondicionocupacion(idCondicion);
				encuestado.setCondicionOcupacion(condicionOcupacion);
			}

			return encuestado;

		} catch (Exception e) {
			logger.info("El encuestado es null");
			return null;
		}
	}

	/**
	 * @param json
	 * @return
	 */
	public static final List<InstalacionDomiciliaria> getListInstalacion(
			String json) {
		List<InstalacionDomiciliaria> instalacionDomiciliarias = new LinkedList<InstalacionDomiciliaria>();
		
		try {
			JSONObject fichaJson = new JSONObject(json);
			JSONObject diagnosticoJson = fichaJson.getJSONObject("diagnostico");
			
			// Aguas
			TipoInstalacion aguas = new TipoInstalacion();
			aguas.setIdtipoinstalacion(1);
			
			Integer idAgua = getIntFromCombobox(diagnosticoJson, "agua");
			Detalleinstalaciondomiciliaria detalleAguas = null;
			
			if (idAgua != null) {
				detalleAguas = new Detalleinstalaciondomiciliaria();
				detalleAguas.setIddetalleinstalaciondomiciliaria(idAgua);
			}
			
			InstalacionDomiciliaria instAguas = new InstalacionDomiciliaria();
			instAguas.setTipoInstalacion(aguas);
			instAguas.setDetalleinstalaciondomiciliaria(detalleAguas);
			instalacionDomiciliarias.add(instAguas);

			// Electricidad
			TipoInstalacion electricidad = new TipoInstalacion();
			electricidad.setIdtipoinstalacion(3);
			
			Integer idElectricidad = getIntFromCombobox(diagnosticoJson, "electricidad");
			Detalleinstalaciondomiciliaria detalleElectricidad = null;
			
			if (idElectricidad != null) {
				detalleElectricidad = new Detalleinstalaciondomiciliaria();
				detalleElectricidad.setIddetalleinstalaciondomiciliaria(idElectricidad);
			}
			
			InstalacionDomiciliaria instElectricidad = new InstalacionDomiciliaria();
			instElectricidad.setTipoInstalacion(electricidad);
			instElectricidad.setDetalleinstalaciondomiciliaria(detalleElectricidad);
			instalacionDomiciliarias.add(instElectricidad);

			// Alcantarillado
			TipoInstalacion alcantarillado = new TipoInstalacion();
			alcantarillado.setIdtipoinstalacion(2);
			
			Integer idAlcantarillado = getIntFromCombobox(diagnosticoJson, "alcantarillado");
			Detalleinstalaciondomiciliaria detalleAlcantarillado = null;
			
			if (idAlcantarillado != null) {
				detalleAlcantarillado = new Detalleinstalaciondomiciliaria();
				detalleAlcantarillado.setIddetalleinstalaciondomiciliaria(idAlcantarillado);
			}
			
			InstalacionDomiciliaria instAlcantarillado = new InstalacionDomiciliaria();
			instAlcantarillado.setTipoInstalacion(alcantarillado);
			instAlcantarillado.setDetalleinstalaciondomiciliaria(detalleAlcantarillado);
			instalacionDomiciliarias.add(instAlcantarillado);
			
		} catch (Exception e) {
			logger.info("No existe lista instalacion");
		}

		return instalacionDomiciliarias;
	}
	
	/**
	 * @param idTipoDanio
	 * @param item
	 * @param list
	 */
	private static final void setDanioVivienda(Integer idTipoDanio, Integer item, List<DanoVivienda> list) {
		if (idTipoDanio != null && list != null) {	
			ItemDano itemDano = new ItemDano();
			itemDano.setIditemdano(item);
			TipoDanoVivienda tipoDanoVivienda = new TipoDanoVivienda();
			tipoDanoVivienda.setIdtipodanovivienda(idTipoDanio);
			DanoVivienda vivienda = new DanoVivienda();
			vivienda.setItemDano(itemDano);
			vivienda.setTipoDanoVivienda(tipoDanoVivienda);
			list.add(vivienda);
		}
	}

	/**
	 * @param json
	 * @return
	 */
	public static final List<DanoVivienda> getDanioList(String json) {
		List<DanoVivienda> danoViviendas = new LinkedList<DanoVivienda>();
		
		try {
			JSONObject fichaJson = new JSONObject(json);
			JSONObject evaJson = fichaJson.getJSONObject("evaluacion");

			// Pilares
			Integer idPilares = getIntFromCombobox(evaJson, "pilares");
			setDanioVivienda(idPilares, 1, danoViviendas);

			// cadenas
			Integer idCadenas = getIntFromCombobox(evaJson, "cadenas");
			setDanioVivienda(idCadenas, 2, danoViviendas);
			
			// Vigas
			Integer idVigas = getIntFromCombobox(evaJson, "vigas");
			setDanioVivienda(idVigas, 3, danoViviendas);

			// muros estructurales
			Integer idMurosEst = getIntFromCombobox(evaJson, "muros");
			setDanioVivienda(idMurosEst, 4, danoViviendas);

			// entrepiso
			Integer idEntrepiso = getIntFromCombobox(evaJson, "entrepiso");
			setDanioVivienda(idEntrepiso, 5, danoViviendas);

			// techumbre
			Integer idTechumbre = getIntFromCombobox(evaJson, "techumbre");
			setDanioVivienda(idTechumbre, 6, danoViviendas);
			
			// ventanas
			Integer idVentanas = getIntFromCombobox(evaJson, "ventanas");
			setDanioVivienda(idVentanas, 7, danoViviendas);

			// puertas
			Integer idPuertas = getIntFromCombobox(evaJson, "puertas");
			setDanioVivienda(idPuertas, 8, danoViviendas);
			
			// rev pisos
			Integer idPisos = getIntFromCombobox(evaJson, "revestimientoPiso");
			setDanioVivienda(idPisos, 9, danoViviendas);

			// rev muros
			Integer idMuros = getIntFromCombobox(evaJson, "revestimientoMuro");
			setDanioVivienda(idMuros, 10, danoViviendas);
			
			// tabiques
			Integer idTabiques = getIntFromCombobox(evaJson, "tabiques");
			setDanioVivienda(idTabiques, 11, danoViviendas);

			// cielo
			Integer idCielo = getIntFromCombobox(evaJson, "cieloRaso");
			setDanioVivienda(idCielo, 12, danoViviendas);

			// agua
			Integer idAgua = getIntFromCombobox(evaJson, "aguaPotable");
			setDanioVivienda(idAgua, 13, danoViviendas);

			// alcantarillado
			Integer idAlcantarillado = getIntFromCombobox(evaJson, "alcantarillado");
			setDanioVivienda(idAlcantarillado, 14, danoViviendas);

			// electricidad
			Integer idElectricidad = getIntFromCombobox(evaJson, "electricidad");
			setDanioVivienda(idElectricidad, 15, danoViviendas);

			// gas
			Integer idGas = getIntFromCombobox(evaJson, "gas");
			setDanioVivienda(idGas, 16, danoViviendas);

			// cierre antejardin
			Integer idAntejardin = getIntFromCombobox(evaJson, "cierreAntejardin");
			setDanioVivienda(idAntejardin, 17, danoViviendas);

			// cierre perimetral
			Integer idCierrePerimetral = getIntFromCombobox(evaJson, "cierrePerimetral");
			setDanioVivienda(idCierrePerimetral, 18, danoViviendas);

			// terreno
			Integer idTerreno = getIntFromCombobox(evaJson, "terreno");
			setDanioVivienda(idTerreno, 19, danoViviendas);

			// accesos
			Integer idAccesos = getIntFromCombobox(evaJson,	"accesos");
			setDanioVivienda(idAccesos, 20, danoViviendas);

			// escaleras
			Integer idEscaleras = getIntFromCombobox(evaJson, "escaleras");
			setDanioVivienda(idEscaleras, 21, danoViviendas);

			// pasarelas
			Integer idPasarelas = getIntFromCombobox(evaJson, "pasarelas");
			setDanioVivienda(idPasarelas, 22, danoViviendas);

			// taludes
			Integer idTaludes = getIntFromCombobox(evaJson, "taludes");
			setDanioVivienda(idTaludes, 23, danoViviendas);

			// muros contencion
			Integer idMurosCont = getIntFromCombobox(evaJson, "murosContencion");
			setDanioVivienda(idMurosCont, 24, danoViviendas);

			// redes sanitarias
			Integer idRedesSanitarias = getIntFromCombobox(evaJson, "redesSanitarias");
			setDanioVivienda(idRedesSanitarias, 25, danoViviendas);

			// colectores
			Integer idColectores = getIntFromCombobox(evaJson, "colectores");
			setDanioVivienda(idColectores, 26, danoViviendas);

			// postacion
			Integer idPostacion = getIntFromCombobox(evaJson, "postacionViaPublica");
			setDanioVivienda(idPostacion, 27, danoViviendas);
			
		} catch (Exception e) {
			logger.info("Lista de Danio Vivienda es vacía");
		}

		return danoViviendas;
	}

	/**
	 * @param json
	 * @return
	 */
	public static final List<GrupoSecundario> getListGrupoSec(String json) {
		List<GrupoSecundario> grupoSecundarios = new LinkedList<GrupoSecundario>();
		
		try {
			JSONObject fichaJson = new JSONObject(json);
			JSONArray secJsonArr = fichaJson.getJSONArray("listGrupoSecundario");

			for (int i = 0; i < secJsonArr.length(); i++) {
				JSONObject obj = (JSONObject) secJsonArr.get(i);
				GrupoSecundario secundario = new GrupoSecundario();
				Persona persona = new Persona();
				persona.setRut(new BigInteger(Integer
						.toString((Integer) jsonGetById(obj, "run"))));
				persona.setDigitoverificador((String) jsonGetById(obj, "dv"));
				persona.setNombres((String) jsonGetById(obj, "nombre"));
				persona.setApellidopaterno((String) jsonGetById(obj,
						"apellidoPaterno"));
				persona.setTelefono((Integer) jsonGetById(obj, "telefono"));
				secundario.setPersona(persona);
				secundario.setTotalgrupo((Integer) jsonGetById(obj,
						"totalIntegrantes"));
				
				Integer idOcupacion = getIntFromCombobox(obj, "ocupacionVivienda");
				
				if (idOcupacion != null) {
					OcupacionVivienda ocupacionVivienda = new OcupacionVivienda();
					ocupacionVivienda.setIdocupacionvivienda(idOcupacion);
					secundario.setOcupacionVivienda(ocupacionVivienda);
				}
				
				grupoSecundarios.add(secundario);
			}
		} catch (Exception e) {
			logger.info("Lista secundaria está vacía");
		}

		return grupoSecundarios;
	}

	/**
	 * @param json
	 * @return
	 */
	public static final Encuestador getEncuestador(String json) {
		Encuestador enc = null;

		try {
			JSONObject jsonObj = new JSONObject(json);
			Encuestador encuestador = new Encuestador();
			encuestador
					.setProfesion((String) jsonGetById(jsonObj, "profesion"));
			encuestador.setPassword((String) jsonGetById(jsonObj, "passwd"));
			encuestador.setToken((String) jsonGetById(jsonObj, "token"));
			encuestador.setEmail((String) jsonGetById(jsonObj, "email"));

			Persona persona = new Persona();
			persona.setApellidopaterno((String) jsonGetById(jsonObj,
					"apellidoPaterno"));
			persona.setApellidomaterno((String) jsonGetById(jsonObj,
					"apellidoMaterno"));
			persona.setRut(new BigInteger(Integer
					.toString((Integer) jsonGetById(jsonObj, "run"))));
			persona.setDigitoverificador((String) jsonGetById(jsonObj, "dv"));
			persona.setNombres((String) jsonGetById(jsonObj, "nombres"));
			encuestador.setPersona(persona);

			Direccion direccion = new Direccion();
			Region region = new Region();
			region.setIdregion((Integer) jsonGetById(jsonObj, "region"));
			Comuna comuna = new Comuna();
			comuna.setIdcomuna((Integer) jsonGetById(jsonObj, "comuna"));
			comuna.setRegion(region);
			direccion.setComuna(comuna);
			encuestador.setDireccion(direccion);

			enc = encuestador;

		} catch (Exception e) {
			logger.error("Error formando el JSON - " + e.getMessage());
		}

		return enc;
	}

	/**
	 * @param key
	 * @return
	 */
	public static final Object jsonGetById(JSONObject json, String key) {
		try {
			return json.get(key);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @param query
	 * @return
	 */
	public static final Map<String, String> getQueryMap(String query) {
		String[] params = query.split("&");
		String foto = null;
		String ficha= null;
		
		Map<String, String> map = null;

		try {
			for (String param : params) {
				String name = param.split("=")[0];
				
				if (name != null && name.equals("object")) {
					ficha = param.split("=")[1];
				} else if (name != null && name.equals("foto")) {
					foto = param.split("=")[1];
				}
			}
			
		} catch (Exception e) {
			logger.error("Error al mapear el request");
		}
		
		if (ficha != null) {
			map = new HashMap<String, String>();
			map.put("object", ficha);
			
			if (foto != null) {
				map.put("foto", foto);
			}
		}

		return map;
	}
	
	/**
	 * @param value
	 * @return
	 */
	public static final byte[] stringToBytes(String value) {
		try {
			return value.getBytes();
		} catch (Exception e) {
			return null;
		}
	}

}
